from FitnessFunction import Fitness
import numpy as np
import scipy.special
from matplotlib import pyplot as plt
import random


class BaseOA():
    """优化算法的基类"""

    def __init__(self, FitFunction, LB, UB, dim, population_size, max_iter):
        """初始化物种优化算法的参数"""
        self.LB = LB  # 搜索空间的左边界
        self.UB = UB  # 搜索空间的右边界
        self.dim = dim  # 位置信息的维度
        self.population_size = population_size  # 种群大小
        self.max_iter = max_iter  # 迭代次数
        self.X = np.zeros((population_size, dim))  # 种群的位置信息
        self.FitFunction = FitFunction
        self.gBest_score = np.inf  # 最优解对应的适应度值
        self.gBest_curve = []  # 每轮的最优解的适应度值
        self.gBest_X = np.zeros(dim)  # 每次迭代得到的最佳位置

    def Initialize_population(self):
        """initialize population 初始化种群数据"""
        # 初始化种群数据X
        for i in range(self.population_size):
            for j in range(self.dim):
                self.X[i, j] = (self.UB[j] - self.LB[j]) * \
                    np.random.random() + self.LB[j]

    def BorderCheck_UpdateFitness(self):
        """边界检查与更新适应度值"""
        for i in range(self.population_size):
            for j in range(self.dim):
                # 检查边界
                for j in range(self.dim):
                    if (self.X[i, j] > self.UB[j]):
                        # 不符合上边界
                        self.X[i, j] = self.UB[j]

                    if (self.X[i, j] < self.LB[j]):
                        # 不符合下边界
                        self.X[i, j] = self.LB[j]
                # 计算所有物种的fitness
                fitness = self.CalculateFitness(self.X[i, :])  # 获取物种的适应度值
                # 更新最优解的适应度值和物种的最优解的位置信息
                if fitness < self.gBest_score:
                    self.gBest_score = fitness
                    self.gBest_X = self.X[i, :].copy()

    def CalculateFitness(self, X):
        """自定义计算适应度函数,计算单个物种的适应度值"""
        fitness = self.FitFunction(X)
        return fitness

    def Optimize(self):
        """重写优化算法的具体实现步骤"""
        pass
